package ar.republicagroup.gestion.dao.jpa;
import ar.republicagroup.gestion.dao.BolsaChequeDAO;
import ar.republicagroup.gestion.entities.BolsaCheque;
import ar.republicagroup.gestion.entities.Cheque;
import ar.republicagroup.gestion.entities.ChequeEstado;
import ar.republicagroup.gestion.entities.Cliente;
import ar.republicagroup.gestion.util.JPAUtil;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.swing.DefaultComboBoxModel;
import org.apache.log4j.Logger;

public class BolsaChequeDAOImplJPA implements BolsaChequeDAO {
    
        private EntityManager		 em;
        private static Logger log = Logger.getLogger(BolsaChequeDAOImplJPA.class);
        

        public BolsaChequeDAOImplJPA() {
            em = JPAUtil.getEntityManager();
        }
    
        public static final int ACTIVO = 1;    

    @Override
    public List<BolsaCheque> findEntities() {
        if(!em.isOpen()){ em = JPAUtil.getEntityManager(); } 
        Query query = em.createQuery("SELECT bc FROM BolsaCheque bc WHERE bc.estado = 1 AND bc.fechaAlta > ?1 AND bc.fechaAlta < ?2 ORDER BY bc.fechaAlta DESC");
        Date hoy = Calendar.getInstance().getTime();
        hoy.setHours(0);
        hoy.setMinutes(0);
        hoy.setSeconds(0);
        
        Date hoy2 = Calendar.getInstance().getTime();
        hoy2.setHours(23);
        hoy2.setMinutes(59);
        hoy2.setSeconds(59);
        
        query.setParameter(1, hoy);
        query.setParameter(2, hoy2);
        return query.getResultList();
        
    }

    @Override
    public String insert(BolsaCheque beanBolsaCheque) {
        
                if(!em.isOpen()){ em = JPAUtil.getEntityManager();}
        
                String resultado = null;
		try{
			em.getTransaction().begin();
			em.persist(beanBolsaCheque);
			em.getTransaction().commit();
			resultado = "Se registró la bolsa correctamente";
                        log.info("Insertando bolsa de cheque..." + " " +"Cliente : "+beanBolsaCheque.getClienteId().getNombre());
                    }catch(Exception ex){
                        log.error("Error al insertar BolsaCheque",ex);
			em.getTransaction().rollback();
                    }
		
                finally{
                        em.close();
                        }
                return resultado;
    }

    @Override
    public String update(BolsaCheque beanBolsaCheque){
        if(!em.isOpen()){ em = JPAUtil.getEntityManager(); }
        
        String mensaje = null;
        try{
            em.getTransaction().begin();
            em.merge(beanBolsaCheque);
            em.getTransaction().commit();
            mensaje = "Update ok!";
        }catch(Exception ex){
            log.error("Error al actualizar BolsaCheque",ex);
            em.getTransaction().rollback();
        }
        
        return mensaje;
    }

    @Override
    public BolsaCheque get(Integer id_bolsacheque) {
       log.info("Obteniendo cheque con id "+id_bolsacheque); 
       if(!em.isOpen()){ em = JPAUtil.getEntityManager(); }
       return em.find(BolsaCheque.class, id_bolsacheque);
    }

    @Override
    public String delete(Integer id_bolsacheque) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public DefaultComboBoxModel combo() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public List<BolsaCheque> getBolsaChequeByFilters(Cliente cliente,Date fechaDesde,Date fechaHasta,ChequeEstado chequeEstado,boolean toLiquid,Calendar fechaLiquidacion) {
                log.info("Obteniendo getBolsaChequesByFilters()");
                
                    if(!em.isOpen()){ em = JPAUtil.getEntityManager(); }
                
                    CriteriaBuilder qb              = em.getCriteriaBuilder();
		    CriteriaQuery cq                = qb.createQuery();
                    Root<BolsaCheque> bolsaCheque   = cq.from(BolsaCheque.class);
                    List<Predicate> predicates      = new ArrayList<>();
                    
                                        
                 if (bolsaCheque != null) {
                       if(toLiquid == true){       
                            Date fechaIni = fechaLiquidacion.getTime();
                            fechaIni.setHours(0);
                            fechaIni.setMinutes(0);
                            fechaIni.setSeconds(0);
                            Date fechaFin = fechaLiquidacion.getTime();
                            fechaFin.setHours(23);
                            fechaFin.setMinutes(59);
                            fechaFin.setSeconds(59);
                            predicates.add(qb.lessThanOrEqualTo(bolsaCheque.get("fechaAlta").as(Date.class), fechaFin));
                            
                        }
                        
                        if(cliente != null){
                            predicates.add(qb.equal(bolsaCheque.get("clienteId"), cliente));
                        }
                        
                        if( (fechaDesde != null) && (fechaHasta != null) ){
                            
                            fechaDesde.setHours(0);
                            fechaDesde.setMinutes(0);
                            fechaDesde.setSeconds(0);
                            
                            fechaHasta.setHours(23);
                            fechaHasta.setMinutes(59);
                            fechaHasta.setSeconds(59);
                            predicates.add(qb.between(bolsaCheque.get("fechaAlta").as(Date.class), fechaDesde, fechaHasta));
                        }
                            predicates.add(qb.equal(bolsaCheque.get("estado"), 1));
                    }
                   
                            cq.select(bolsaCheque)
		            .where(predicates.toArray(new Predicate[]{}));
                            cq.orderBy(qb.desc(bolsaCheque.get("fechaAlta").as(Date.class)));
                            List<BolsaCheque> bolsaChequeList =  em.createQuery(cq).getResultList();
                    
                        if(chequeEstado != null){
                            bolsaChequeList = filtrarPorChequeEstado(bolsaChequeList, chequeEstado);
                        }
                        
                    return bolsaChequeList;
      }

    /**
     * Filtra sólo las bolsas que contengan al menos un cheque con el estado enviado .
     * @param bolsaChequeList, un List con todas las bolsas encontradas de acuerdo a los filtros .
     * @param chequeEstado , el estado del Cheque para filtrar las bolsas .
     * @return List<BolsaCheque> filtrada por un estado de cheque
     */
    
    public List<BolsaCheque> filtrarPorChequeEstado(List<BolsaCheque> bolsaChequeList,ChequeEstado chequeEstado){
            List<BolsaCheque> listado = new ArrayList<>();
            boolean agregar = false;
            
            for(BolsaCheque bolsa : bolsaChequeList){
                for(Cheque cheque: bolsa.getChequeList()){
                    if(cheque.getChequeEstadoId().getId() == chequeEstado.getId() && cheque.getEstado() == ACTIVO){
                        agregar = true;
                    }
                }
                         if(agregar){
                            listado.add(bolsa);
                                    }
                        agregar = false;
            }
            return listado;
    }
   
}